From fb542e56483f1f280f93781de7af3c983135653a Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Wed, 21 Sep 2005 16:36:46 +0000 Subject: [PATCH] Fix mapping of shared ring pages into backend drivers. This should fix observed problems when creating a domain, causing Xen to print "Could not find PTE entry for address ...". Signed-off-by: Keir Fraser --- linux-2.6-xen-sparse/drivers/xen/Makefile | 1 + .../drivers/xen/blkback/interface.c | 9 ++-- .../drivers/xen/blktap/interface.c | 9 ++-- .../drivers/xen/netback/interface.c | 9 ++-- .../drivers/xen/tpmback/interface.c | 11 +++-- .../drivers/xen/usbback/interface.c | 9 ++-- linux-2.6-xen-sparse/drivers/xen/util.c | 46 +++++++++++++++++++ .../include/asm-xen/driver_util.h | 10 ++++ 8 files changed, 83 insertions(+), 21 deletions(-) create mode 100644 linux-2.6-xen-sparse/drivers/xen/util.c create mode 100644 linux-2.6-xen-sparse/include/asm-xen/driver_util.h diff --git a/linux-2.6-xen-sparse/drivers/xen/Makefile b/linux-2.6-xen-sparse/drivers/xen/Makefile index 83f63cd7bb..d7a3e80ccd 100644 --- a/linux-2.6-xen-sparse/drivers/xen/Makefile +++ b/linux-2.6-xen-sparse/drivers/xen/Makefile @@ -1,4 +1,5 @@ +obj-y += util.o obj-y += console/ obj-y += evtchn/ diff --git a/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c b/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c index 79b37abc09..a31fc0964b 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c @@ -8,6 +8,7 @@ #include "common.h" #include +#include static kmem_cache_t *blkif_cachep; @@ -69,12 +70,12 @@ int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn) BUG_ON(blkif->remote_evtchn); - if ( (vma = get_vm_area(PAGE_SIZE, VM_IOREMAP)) == NULL ) + if ( (vma = prepare_vm_area(PAGE_SIZE)) == NULL ) return -ENOMEM; err = map_frontend_page(blkif, (unsigned long)vma->addr, shared_page); if (err) { - vfree(vma->addr); + vunmap(vma->addr); return err; } @@ -85,7 +86,7 @@ int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn) err = HYPERVISOR_event_channel_op(&op); if (err) { unmap_frontend_page(blkif); - vfree(vma->addr); + vunmap(vma->addr); return err; } @@ -123,7 +124,7 @@ static void free_blkif(void *arg) if (blkif->blk_ring.sring) { unmap_frontend_page(blkif); - vfree(blkif->blk_ring.sring); + vunmap(blkif->blk_ring.sring); blkif->blk_ring.sring = NULL; } diff --git a/linux-2.6-xen-sparse/drivers/xen/blktap/interface.c b/linux-2.6-xen-sparse/drivers/xen/blktap/interface.c index 6f9aae9ccc..28814b5aef 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blktap/interface.c +++ b/linux-2.6-xen-sparse/drivers/xen/blktap/interface.c @@ -8,6 +8,7 @@ #include "common.h" #include +#include static kmem_cache_t *blkif_cachep; @@ -69,12 +70,12 @@ int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn) BUG_ON(blkif->remote_evtchn); - if ( (vma = get_vm_area(PAGE_SIZE, VM_IOREMAP)) == NULL ) + if ( (vma = prepare_vm_area(PAGE_SIZE)) == NULL ) return -ENOMEM; err = map_frontend_page(blkif, (unsigned long)vma->addr, shared_page); if (err) { - vfree(vma->addr); + vunmap(vma->addr); return err; } @@ -85,7 +86,7 @@ int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn) err = HYPERVISOR_event_channel_op(&op); if (err) { unmap_frontend_page(blkif); - vfree(vma->addr); + vunmap(vma->addr); return err; } @@ -121,7 +122,7 @@ static void free_blkif(void *arg) if (blkif->blk_ring.sring) { unmap_frontend_page(blkif); - vfree(blkif->blk_ring.sring); + vunmap(blkif->blk_ring.sring); blkif->blk_ring.sring = NULL; } diff --git a/linux-2.6-xen-sparse/drivers/xen/netback/interface.c b/linux-2.6-xen-sparse/drivers/xen/netback/interface.c index 311f426d0b..1f62e35438 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netback/interface.c +++ b/linux-2.6-xen-sparse/drivers/xen/netback/interface.c @@ -8,6 +8,7 @@ #include "common.h" #include +#include static void __netif_up(netif_t *netif) { @@ -198,14 +199,14 @@ int netif_map(netif_t *netif, unsigned long tx_ring_ref, evtchn_op_t op = { .cmd = EVTCHNOP_bind_interdomain }; int err; - vma = get_vm_area(2*PAGE_SIZE, VM_IOREMAP); + vma = prepare_vm_area(2*PAGE_SIZE); if (vma == NULL) return -ENOMEM; err = map_frontend_pages( netif, (unsigned long)vma->addr, tx_ring_ref, rx_ring_ref); if (err) { - vfree(vma->addr); + vunmap(vma->addr); return err; } @@ -216,7 +217,7 @@ int netif_map(netif_t *netif, unsigned long tx_ring_ref, err = HYPERVISOR_event_channel_op(&op); if (err) { unmap_frontend_pages(netif); - vfree(vma->addr); + vunmap(vma->addr); return err; } @@ -261,7 +262,7 @@ static void free_netif_callback(void *arg) if (netif->tx) { unmap_frontend_pages(netif); - vfree(netif->tx); /* Frees netif->rx as well. */ + vunmap(netif->tx); /* Frees netif->rx as well. */ } free_netdev(netif->dev); diff --git a/linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c b/linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c index 3c585e6bcd..d05f91d066 100644 --- a/linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c +++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/interface.c @@ -1,4 +1,4 @@ - /****************************************************************************** + /***************************************************************************** * drivers/xen/tpmback/interface.c * * Vritual TPM interface management. @@ -13,6 +13,7 @@ #include "common.h" #include +#include #define VMALLOC_VMADDR(x) ((unsigned long)(x)) @@ -122,12 +123,12 @@ tpmif_map(tpmif_t * tpmif, unsigned long shared_page, unsigned int evtchn) BUG_ON(tpmif->remote_evtchn); - if ((vma = get_vm_area(PAGE_SIZE, VM_IOREMAP)) == NULL) + if ((vma = prepare_vm_area(PAGE_SIZE)) == NULL) return -ENOMEM; err = map_frontend_page(tpmif, VMALLOC_VMADDR(vma->addr), shared_page); if (err) { - vfree(vma->addr); + vunmap(vma->addr); return err; } @@ -138,7 +139,7 @@ tpmif_map(tpmif_t * tpmif, unsigned long shared_page, unsigned int evtchn) err = HYPERVISOR_event_channel_op(&op); if (err) { unmap_frontend_page(tpmif); - vfree(vma->addr); + vunmap(vma->addr); return err; } @@ -174,7 +175,7 @@ __tpmif_disconnect_complete(void *arg) if (tpmif->tx) { unmap_frontend_page(tpmif); - vfree(tpmif->tx); + vunmap(tpmif->tx); } free_tpmif(tpmif); diff --git a/linux-2.6-xen-sparse/drivers/xen/usbback/interface.c b/linux-2.6-xen-sparse/drivers/xen/usbback/interface.c index ab44ed3040..fe091aad36 100644 --- a/linux-2.6-xen-sparse/drivers/xen/usbback/interface.c +++ b/linux-2.6-xen-sparse/drivers/xen/usbback/interface.c @@ -7,6 +7,7 @@ */ #include "common.h" +#include #define USBIF_HASHSZ 1024 #define USBIF_HASH(_d) (((int)(_d))&(USBIF_HASHSZ-1)) @@ -33,7 +34,7 @@ static void __usbif_disconnect_complete(void *arg) * may be outstanding requests at the device whose asynchronous responses * must still be notified to the remote driver. */ - vfree(usbif->usb_ring.sring); + vunmap(usbif->usb_ring.sring); /* Construct the deferred response message. */ cmsg.type = CMSG_USBIF_BE; @@ -154,7 +155,7 @@ void usbif_connect(usbif_be_connect_t *connect) return; } - if ( (vma = get_vm_area(PAGE_SIZE, VM_IOREMAP)) == NULL ) + if ( (vma = prepare_vm_area(PAGE_SIZE)) == NULL ) { connect->status = USBIF_BE_STATUS_OUT_OF_MEMORY; return; @@ -172,14 +173,14 @@ void usbif_connect(usbif_be_connect_t *connect) connect->status = USBIF_BE_STATUS_MAPPING_ERROR; else connect->status = USBIF_BE_STATUS_ERROR; - vfree(vma->addr); + vunmap(vma->addr); return; } if ( up->status != DISCONNECTED ) { connect->status = USBIF_BE_STATUS_INTERFACE_CONNECTED; - vfree(vma->addr); + vunmap(vma->addr); return; } diff --git a/linux-2.6-xen-sparse/drivers/xen/util.c b/linux-2.6-xen-sparse/drivers/xen/util.c new file mode 100644 index 0000000000..04c5984cd4 --- /dev/null +++ b/linux-2.6-xen-sparse/drivers/xen/util.c @@ -0,0 +1,46 @@ +#include +#include +#include +#include +#include + +static int touch_fn( + pte_t *pte, struct page *pte_page, unsigned long addr, void *data) +{ + char c; + BUG_ON(!__get_user(c, (char *)addr)); + return 0; +} + +struct vm_struct *prepare_vm_area(unsigned long size) +{ + struct vm_struct *area; + + area = get_vm_area(size, VM_IOREMAP); + if (area == NULL) + return NULL; + + /* + * This ensures that page tables are constructed for this region + * of kernel virtual address space. Furthermore, by touching each + * memory page (in touch_fn()) we ensure that the page tables are + * mapped into the current mm as well as init_mm. + */ + if (generic_page_range(&init_mm, (unsigned long)area->addr, + area->size, touch_fn, NULL)) { + vunmap(area->addr); + return NULL; + } + + return area; +} + +/* + * Local variables: + * c-file-style: "linux" + * indent-tabs-mode: t + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ diff --git a/linux-2.6-xen-sparse/include/asm-xen/driver_util.h b/linux-2.6-xen-sparse/include/asm-xen/driver_util.h new file mode 100644 index 0000000000..142b228238 --- /dev/null +++ b/linux-2.6-xen-sparse/include/asm-xen/driver_util.h @@ -0,0 +1,10 @@ + +#ifndef __ASM_XEN_DRIVER_UTIL_H__ +#define __ASM_XEN_DRIVER_UTIL_H__ + +#include +#include + +extern struct vm_struct *prepare_vm_area(unsigned long size); + +#endif /* __ASM_XEN_DRIVER_UTIL_H__ */ -- 2.30.2